//
//  MCNNavigationBarNavigationController.swift
//  MCNNavigationBarNavigationController
//
//  Created by yhbj on 2021/9/17.
//

import UIKit

class MCNNavigationBarNavigationController: UINavigationController, UIGestureRecognizerDelegate, UINavigationControllerDelegate {
    
    /**
     是否禁用push控制器自动隐藏tabbar
     */
    var mcn_disableAutoHidesBottomBarWhenPushed: Bool = false

    /**
    pop返回手势对象
    */
    private(set) var mcn_popGestureRecognizer: UIPanGestureRecognizer?

    /**
     是否禁用全屏pop手势，若禁用，则pop触发范围为屏幕宽度的十分之一
     */
    var mcn_disableFullScreenGesture: Bool = false {
        didSet {
            if mcn_disableFullScreenGesture {
                mcn_popGestureCoverRatio = 0.1
            } else {
                mcn_popGestureCoverRatio = 1
            }
        }
    }

    /**
     pop手势的触发范围比例，0-1，默认为1，即代表全屏触发
     */
    var mcn_popGestureCoverRatio: CGFloat = 1 {
        didSet {
            if mcn_popGestureCoverRatio > 1 {
                mcn_popGestureCoverRatio = 1
            } else if mcn_popGestureCoverRatio < 0 {
                mcn_popGestureCoverRatio = 0
            }
        }
    }

    /**
     监听自定义pop手势进度。currentViewController代表当前正在pop的控制器，popOffsetProgress范围为0-1，0代表即将开始pop，1代表完成pop
     */
    var mcn_handleCustomPopGesture: ((_ currentViewController: UIViewController, _ popOffsetProgress: CGFloat) -> ())?

    /**
    pop手势是否支持多层级的手势同时触发，默认为否
    */
    var mcn_popGestureShouldRecognizeSimultaneously: ((_ otherGestureRecognizer: UIGestureRecognizer) -> (Bool))?

    /**
     拦截导航控制器侧滑返回手势，若返回NO，则禁止pop;
     topViewController:当前控制器
    */
    var mcn_navHandlePopGestureBlock: ((_ topViewController: UIViewController) -> (Bool))?
    
    var touchBeginX: CGFloat = 0
    var doingPopGesture: Bool = false
    var mcn_topViewController: UIViewController?
    var orgInteractivePopGestureRecognizerDelegate: AnyObject?
    
    override func viewDidLoad() {
        orgInteractivePopGestureRecognizerDelegate = interactivePopGestureRecognizer?.delegate
        super.viewDidLoad()
        delegate = self
        mcn_popGestureCoverRatio = 1
        
    }
    
    //MARK: - 添加全屏手势
    private func addFullScreenGesture() {
        self.interactivePopGestureRecognizer?.isEnabled = false
        let popGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handleNavigationTransition(panGesture:)))
        view.addGestureRecognizer(popGestureRecognizer)
        mcn_popGestureRecognizer = popGestureRecognizer
    }
    
    //MARK: - 处理pop手势
    @objc func handleNavigationTransition(panGesture: UIGestureRecognizer) {
        if mcn_topViewController != nil && !doingPopGesture {
            if mcn_topViewController!.isKind(of: MCNNavigationBarTableViewController.classForCoder()) {
                let topViewController = mcn_topViewController as! MCNNavigationBarTableViewController
                if topViewController.mcn_handlePopBlock != nil {
                    let shouldPop = topViewController.mcn_handlePopBlock!(mcn_topViewController as! MCNNavigationBarTableViewController, MCNNavPopBlockFrom.PopGesture)
                    if !shouldPop {
                        return
                    }
                }
            } else {
                let topViewController = mcn_topViewController as! MCNNavigationBarController
                if topViewController.mcn_handlePopBlock != nil {
                    let shouldPop = topViewController.mcn_handlePopBlock!(mcn_topViewController as! MCNNavigationBarController, .PopGesture)
                    if !shouldPop {
                        return
                    }
                }
            }
        }
        if mcn_navHandlePopGestureBlock != nil {
            let shouldPop = mcn_navHandlePopGestureBlock!(mcn_topViewController!)
            if !shouldPop {
                return
            }
        }
        let panGestureX = panGesture.location(in: view).x
        doingPopGesture = true
        if orgInteractivePopGestureRecognizerDelegate != nil {
            _ = orgInteractivePopGestureRecognizerDelegate!.perform(#selector(handleNavigationTransition(panGesture:)), with: panGesture)
        }
        let popOffsetX = panGestureX - touchBeginX
        if mcn_handleCustomPopGesture != nil {
            if panGesture.state == .ended {
                doingPopGesture = false
                if popOffsetX > view.mcn_width / 2 {
                    if #available(iOS 10.0, *) {
                        
                    } else {
                        mcn_handleCustomPopGesture!(mcn_topViewController!, 1)
                    }
                } else {
                    if #available(iOS 10.0, *) {
                        
                    } else {
                        mcn_handleCustomPopGesture!(mcn_topViewController!, 0)
                    }
                }
            } else {
                if popOffsetX >= 0 {
                    mcn_handleCustomPopGesture!(mcn_topViewController!, (popOffsetX / view.mcn_width))
                } else {
                    mcn_handleCustomPopGesture!(mcn_topViewController!, 0)
                }
            }
        }
    }
    
    //MARK: - 更新栈顶控制器
    func updateTopViewController(viewController: UIViewController?) {
        mcn_topViewController = nil
        if viewController != nil && (viewController!.isKind(of: MCNNavigationBarController.classForCoder()) || viewController!.isKind(of: MCNNavigationBarTableViewController.classForCoder())) {
            if viewController!.isKind(of: MCNNavigationBarController.classForCoder()) {
                mcn_topViewController = viewController as! MCNNavigationBarController
            } else {
                mcn_topViewController = viewController as! MCNNavigationBarTableViewController
            }
        }
    }
    
    //MARK: - UIGestureRecognizerDelegate
    private func gestureRecognizerShouldBegin(_ gestureRecognizer: UIPanGestureRecognizer) -> Bool {
        if gestureRecognizer != mcn_popGestureRecognizer {
            return true
        }
        if (value(forKey: "_isTransitioning") as! Bool) {
            return false
        }
        let translation = gestureRecognizer.translation(in: view)
        let isLeftToRight = UIApplication.shared.userInterfaceLayoutDirection == .leftToRight
        let multiplier: CGFloat = isLeftToRight ? 1 : -1
        if (translation.x * multiplier) <= 0 {
            return false
        }
        let panGestureX = gestureRecognizer.location(in: view).x
        let coverW = mcn_popGestureCoverRatio * view.mcn_width
        if panGestureX > coverW {
            return false
        }
        touchBeginX = gestureRecognizer.location(in: view).x
        return childViewControllers.count != 1
    }
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        var shouldRecognizeSimultaneously = false
        if mcn_popGestureShouldRecognizeSimultaneously != nil {
            shouldRecognizeSimultaneously = mcn_popGestureShouldRecognizeSimultaneously!(otherGestureRecognizer)
        }
        return shouldRecognizeSimultaneously
    }
    
    //MARK: - UINavigationControllerDelegate
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        if topViewController != nil {
            let transitionCoordinator = topViewController!.transitionCoordinator
            if transitionCoordinator != nil {
                if #available(iOS 10.0, *) {
                    transitionCoordinator?.notifyWhenInteractionChanges({ context in
                        if context.isCancelled {
                            if self.mcn_handleCustomPopGesture != nil {
                                self.mcn_handleCustomPopGesture!(self.mcn_topViewController!, 0)
                            }
                        } else {
                            if self.mcn_handleCustomPopGesture != nil {
                                self.mcn_handleCustomPopGesture!(self.mcn_topViewController!, 1)
                            }
                        }
                    })
                }
            }
        }
    }
}
